/**
 * @file
 * @brief 板级描述层：初始化
 * @author
 * + 隐星魂 (Roy Sun) <xwos@xwos.tech>
 * @copyright
 * + Copyright © 2015 xwos.tech, All Rights Reserved.
 * > Licensed under the Apache License, Version 2.0 (the "License");
 * > you may not use this file except in compliance with the License.
 * > You may obtain a copy of the License at
 * >
 * >         http://www.apache.org/licenses/LICENSE-2.0
 * >
 * > Unless required by applicable law or agreed to in writing, software
 * > distributed under the License is distributed on an "AS IS" BASIS,
 * > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * > See the License for the specific language governing permissions and
 * > limitations under the License.
 */

#include "Board/std.h"
#include <xwcd/soc/arm/v7m/arch_init.h>
#include <xwcd/soc/arm/v7m/m4/stm32/soc_init.h>
#include <string.h>
#include <xwos/mm/bma.h>
#include <xwos/mm/mempool/allocator.h>
#include <xwos/mp/thd.h>
#include <xwos/mp/swt.h>
#include <xwos/mp/sync/sem.h>
#include <xwos/mp/sync/cond.h>
#include <xwos/mp/sync/evt.h>
#include <xwos/mp/lock/mtx.h>
#include "XWAC/xwos/pm.h"
#include "XWAC/xwds/device.h"
#include "STM32Cube/mif.h"

#define STKMEMPOOL_BLKSZ BRDCFG_MM_STKMEMPOOL_BLKSZ
#define STKMEMPOOL_BLKODR BRDCFG_MM_STKMEMPOOL_BLKODR
extern xwsz_t stkmempool_mr_origin[];
extern xwsz_t stkmempool_mr_size[];
/**
 * @brief thread stack mempool zone
 */
__xwbsp_data XWMM_BMA_DEF(stkmempool_bma_objrawmem, STKMEMPOOL_BLKODR);
__xwbsp_data struct xwmm_bma * stkmempool_bma = (void *)&stkmempool_bma_objrawmem;

extern xwsz_t ccmram_mr_origin[];
extern xwsz_t ccmram_mr_size[];
extern xwsz_t ccmram_mr_pos[];
#define CCMRAM_PAGE_ORDER 4 /* 64K / 4K == 16 == exp2(4) */
/**
 * @brief CCMRAM内存池
 * @note
 * + 头文件
 *   - Board/ccmram.h
 * + API
 *   - 申请：xwmm_mempool_malloc(ccmram_mempool, ...)
 *   - 释放：xwmm_mempool_free(ccmram_mempool, ...)
 *   - 重新申请：xwmm_mempool_realloc(ccmram_mempool, ...)
 */
__xwbsp_data XWMM_MEMPOOL_DEF(ccmram_mempool, CCMRAM_PAGE_ORDER);

extern xwsz_t sdram_mr_origin[];
extern xwsz_t sdram_mr_size[];

/**
 * @brief SDRAM内存池
 * @note
 * + 头文件
 *   + `Board/sdram.h`
 * + API
 *   + 申请： `xwmm_mempool_malloc(sdram_mempool, ...)`
 *   + 释放： `xwmm_mempool_free(sdram_mempool, ...)`
 *   + 重新申请： `xwmm_mempool_realloc(sdram_mempool, ...)`
 */
struct xwmm_mempool * sdram_mempool = (void *)sdram_mr_origin;

/**
 * @brief 初始化内存管理
 */
static __xwbsp_init_code
void board_mm_init(void)
{
        xwer_t rc;
        xwssq_t odr;
        xwsz_t used;

        rc = xwmm_bma_init(stkmempool_bma, "stkmempool",
                           (xwptr_t)stkmempool_mr_origin,
                           (xwsz_t)stkmempool_mr_size,
                           (xwsz_t)STKMEMPOOL_BLKSZ,
                           (xwsz_t)STKMEMPOOL_BLKODR);
        BOARD_BUG_ON(rc < 0);

        used = (xwsz_t)ccmram_mr_pos - (xwsz_t)ccmram_mr_origin;
        rc = xwmm_mempool_init((struct xwmm_mempool *)ccmram_mempool, "CCMRAM",
                               (xwptr_t)ccmram_mr_origin,
                               (xwsz_t)ccmram_mr_size,
                               (xwsz_t)CCMRAM_PAGE_ORDER,
                               used, NULL);
        BOARD_BUG_ON(rc < 0);

        odr = xwbop_fls(xwsz_t, (xwsz_t)sdram_mr_size / XWMM_MEMPOOL_PAGE_SIZE);
        rc = xwmm_mempool_init(sdram_mempool, "SDRAM",
                               (xwptr_t)sdram_mr_origin,
                               (xwsz_t)sdram_mr_size,
                               (xwsz_t)odr,
                               (xwsz_t)0, NULL);
        BOARD_BUG_ON(rc < 0);

        rc = xwmp_thd_cache_init((struct xwmm_mempool *)ccmram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_THD_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwmp_swt_cache_init((struct xwmm_mempool *)ccmram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_SWT_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwmp_sem_cache_init((struct xwmm_mempool *)ccmram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_SEM_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwmp_cond_cache_init((struct xwmm_mempool *)ccmram_mempool,
                                  (xwsz_t)BRDCFG_XWOS_COND_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwmp_evt_cache_init((struct xwmm_mempool *)ccmram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_EVT_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwmp_mtx_cache_init((struct xwmm_mempool *)ccmram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_MTX_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);
}

/**
 * @brief XWOS预初始化
 */
__xwbsp_init_code
void xwos_preinit(void)
{
        arch_init();
        soc_init();
        stm32cube_preinit();
        soc_relocate_data();
        soc_relocate_ivt();
        stm32cube_init();
}

/**
 * @brief XWOS后初始化
 */
__xwbsp_init_code
void xwos_postinit(void)
{
        stm32xwds_init();
        stm32xwds_soc_init();
        xwosac_pmcb_init();
        board_mm_init();
}
